/**
 * 金额处理工具类
 * 解决浮点数精度问题，确保金额始终保持两位小数
 */

class MoneyUtils {
  /**
   * 格式化金额为两位小数
   * @param {number|string} amount 金额
   * @returns {number} 格式化后的金额
   */
  static formatAmount(amount) {
    if (amount === null || amount === undefined || amount === '') {
      return 0.00;
    }
    
    // 转换为数字
    const num = parseFloat(amount);
    
    // 检查是否为有效数字
    if (isNaN(num)) {
      console.warn('金额格式错误:', amount);
      return 0.00;
    }
    
    // 保留两位小数并转换为数字
    return parseFloat(num.toFixed(2));
  }

  /**
   * 格式化金额为显示字符串
   * @param {number|string} amount 金额
   * @param {string} prefix 前缀，默认为 ¥
   * @returns {string} 格式化后的显示字符串
   */
  static formatDisplay(amount, prefix = '¥') {
    const formattedAmount = this.formatAmount(amount);
    return `${prefix}${formattedAmount.toFixed(2)}`;
  }

  /**
   * 金额加法运算
   * @param {number|string} a 加数
   * @param {number|string} b 被加数
   * @returns {number} 运算结果
   */
  static add(a, b) {
    const numA = this.formatAmount(a);
    const numB = this.formatAmount(b);
    
    // 转换为整数进行运算，避免浮点数精度问题
    const result = (Math.round(numA * 100) + Math.round(numB * 100)) / 100;
    return this.formatAmount(result);
  }

  /**
   * 金额减法运算
   * @param {number|string} a 被减数
   * @param {number|string} b 减数
   * @returns {number} 运算结果
   */
  static subtract(a, b) {
    const numA = this.formatAmount(a);
    const numB = this.formatAmount(b);
    
    const result = (Math.round(numA * 100) - Math.round(numB * 100)) / 100;
    return this.formatAmount(result);
  }

  /**
   * 金额乘法运算
   * @param {number|string} a 被乘数
   * @param {number|string} b 乘数
   * @returns {number} 运算结果
   */
  static multiply(a, b) {
    const numA = this.formatAmount(a);
    const numB = parseFloat(b) || 0;
    
    const result = (Math.round(numA * 100) * numB) / 100;
    return this.formatAmount(result);
  }

  /**
   * 金额除法运算
   * @param {number|string} a 被除数
   * @param {number|string} b 除数
   * @returns {number} 运算结果
   */
  static divide(a, b) {
    const numA = this.formatAmount(a);
    const numB = parseFloat(b) || 1;
    
    if (numB === 0) {
      console.warn('除数不能为0');
      return 0.00;
    }
    
    const result = (Math.round(numA * 100) / numB) / 100;
    return this.formatAmount(result);
  }

  /**
   * 验证金额格式是否正确
   * @param {number|string} amount 金额
   * @returns {boolean} 是否为有效金额
   */
  static isValidAmount(amount) {
    if (amount === null || amount === undefined || amount === '') {
      return false;
    }
    
    const num = parseFloat(amount);
    return !isNaN(num) && num >= 0;
  }

  /**
   * 比较两个金额大小
   * @param {number|string} a 金额A
   * @param {number|string} b 金额B
   * @returns {number} -1: a<b, 0: a=b, 1: a>b
   */
  static compare(a, b) {
    const numA = this.formatAmount(a);
    const numB = this.formatAmount(b);
    
    if (numA < numB) return -1;
    if (numA > numB) return 1;
    return 0;
  }

  /**
   * 获取金额的整数部分
   * @param {number|string} amount 金额
   * @returns {number} 整数部分
   */
  static getIntegerPart(amount) {
    const num = this.formatAmount(amount);
    return Math.floor(num);
  }

  /**
   * 获取金额的小数部分
   * @param {number|string} amount 金额
   * @returns {number} 小数部分（保留两位）
   */
  static getDecimalPart(amount) {
    const num = this.formatAmount(amount);
    return parseFloat((num % 1).toFixed(2));
  }

  /**
   * 批量格式化金额数组
   * @param {Array} amounts 金额数组
   * @returns {Array} 格式化后的金额数组
   */
  static formatAmounts(amounts) {
    if (!Array.isArray(amounts)) {
      return [];
    }
    
    return amounts.map(amount => this.formatAmount(amount));
  }

  /**
   * 计算金额数组的总和
   * @param {Array} amounts 金额数组
   * @returns {number} 总和
   */
  static sum(amounts) {
    if (!Array.isArray(amounts)) {
      return 0.00;
    }
    
    let total = 0;
    amounts.forEach(amount => {
      total = this.add(total, amount);
    });
    
    return total;
  }
}

module.exports = MoneyUtils;